package org.budo.graph.service.util;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.budo.support.lang.util.MapUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.spring.util.SpringUtil;
import org.springframework.context.ApplicationContext;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.dubbo.config.MethodConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.spring.ServiceBean;

/**
 * @author lmw
 */
public class DubboServiceUtil {
    public static String writeDubboServiceResponse(ApplicationContext applicationContext, String url) {
        List<ServiceBean> serviceBeans = new ArrayList<ServiceBean>();

        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            Object beanInstance = SpringUtil.getBean(applicationContext, beanName);
            if (null == beanInstance) {
                continue;
            }

            if (!(beanInstance instanceof ServiceBean)) {
                continue;
            }

            serviceBeans.add((ServiceBean) beanInstance);
        }

        if (serviceBeans.isEmpty()) {
            return "<h1>no dubbo serviceBean</h1>";
        }

        String response = "<pre>";
        int i = 1;
        for (ServiceBean serviceBean : serviceBeans) {
            response += (i++) + ". " + serviceBeanToString(serviceBean) + "\n";
        }
        return response + "</pre>";
    }

    private static String serviceBeanToString(ServiceBean serviceBean) {
        String version = serviceBean.getVersion();
        String response = serviceBean.getInterface() + ":" + (null == version ? "VERSION_NULL" : version);

        List<ProtocolConfig> protocols = serviceBean.getProtocols();
        if (null != protocols && !protocols.isEmpty()) {
            List<String> protocolNames = new ArrayList<String>();
            for (ProtocolConfig protocol : protocols) {
                String name = protocol.getName();
                protocolNames.add(name);
            }
            response += ", protocols=" + protocolNames;
        }

        Integer timeout = serviceBean.getTimeout();
        if (null != timeout) {
            response += ", timeout=" + timeout;
        }

        Integer executes = serviceBean.getExecutes();
        if (null != executes) {
            response += ", executes=" + executes;
        }

        List<String> methodConfList = new ArrayList<String>();
        List<MethodConfig> methodConfigs = serviceBean.getMethods();
        if (null != methodConfigs && !methodConfigs.isEmpty()) {
            for (MethodConfig methodConfig : methodConfigs) {
                methodConfList.add(methodConfigToString(methodConfig));
            }

            response += ", methods = {" + StringUtil.join(methodConfList, ",\n\t") + "}";
        }

        return response;
    }

    private static String methodConfigToString(MethodConfig methodConfig) {
        List<String> methodConf = new ArrayList<String>();
        Integer methodTimeout = methodConfig.getTimeout();
        if (null != methodTimeout) {
            methodConf.add("timeout = " + methodTimeout);
        }

        Integer methodExecutes = methodConfig.getExecutes();
        if (null != methodExecutes) {
            methodConf.add("executes = " + methodExecutes);
        }

        return methodConfig.getName() + "={" + StringUtil.join(methodConf) + "}";
    }

    public static String writeDubboServiceJsonResponse(ApplicationContext applicationContext, String url) {
        Set<Map<String, Object>> services = new HashSet<Map<String, Object>>();

        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            Object beanInstance = SpringUtil.getBean(applicationContext, beanName, true);
            if (null == beanInstance) {
                continue;
            }

            if (!(beanInstance instanceof ServiceBean)) {
                continue;
            }

            ServiceBean serviceBean = (ServiceBean) beanInstance;
            String interfaceName = serviceBean.getInterface();
            services.add(MapUtil.stringObjectMap("interface", interfaceName));
        }

        return JSONUtils.toJSONString(services);
    }
}